package com.tengju.settlement.application.depository;

import com.tengju.settlement.application.shared.ApplicationException;
import com.tengju.settlement.application.shared.ApplicationExceptionCode;
import com.tengju.settlement.domain.model.account.UserIdCode;
import com.tengju.settlement.domain.model.depository.*;
import com.tengju.settlement.domain.service.RemotePaymentService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor(onConstructor_ = {@Autowired})
public class DepositoryService {

    private final DepositoryAccountRepository depositoryAccountRepository;
    private final DepositoryBankCardRepository depositoryBankCardRepository;
    private final RemotePaymentService remotePaymentService;

    @Transactional(rollbackFor = Exception.class)
    public DepositoryAccount openDepositoryAccount(DepositoryOpenAccountForm form) {

        //用户是否已开户
        List<DepositoryAccount> normalAccounts =
                depositoryAccountRepository.getByIdCodeStatus(form.getIdCode(),
                        List.of(AccountStatus.NORMAL, AccountStatus.CARD_NOT_BIND, AccountStatus.CARD_BINDING), DepositoryChannel.PING_AN);
        if (!CollectionUtils.isEmpty(normalAccounts)) {
            //该证件号已经开户
            for (DepositoryAccount depositoryAccount : normalAccounts) {
                if (depositoryAccount.compareAccountLicense(form.getLicense())) {
                    return depositoryAccount;
                }
            }
        }


        List<DepositoryAccount> accounts = depositoryAccountRepository
                .getByLicenseStatus(form.getLicense(), List.of(AccountStatus.NORMAL,
                        AccountStatus.LOGICAL_CANCEL, AccountStatus.CARD_BINDING, AccountStatus.CARD_NOT_BIND), DepositoryChannel.PING_AN);

        if (!CollectionUtils.isEmpty(accounts) && !accounts.get(0).getIdCode().equals(form.getIdCode())) {
            throw ApplicationException.error(ApplicationExceptionCode.DEP_ACCOUNT_OPEN_LICENSE_HAS_BEEN_USED);
        } else if (!CollectionUtils.isEmpty(accounts) && accounts.get(0).getIdCode().equals(form.getIdCode())) {
            DepositoryAccount account = accounts.get(0);
            //该证件号账户为逻辑注销状态 变更本地状态
            if (AccountStatus.LOGICAL_CANCEL == account.getStatus()) {
                account.changeStatus(AccountStatus.CARD_NOT_BIND);
                depositoryAccountRepository.updateStatus(account);
            }
            return account;
        }


        //平安已开户 同步开户信息
        DepositoryAccount syncDepositoryAccount = accountSync(form.getLicense(), form.getIdCode());
        if (syncDepositoryAccount != null) {
            return syncDepositoryAccount;
        }
        //请求平安开户
        String depositoryId = remotePaymentService.applyOpenAccount(form);
        DepositoryAccount depositoryAccount = new DepositoryAccount(
                null, form.getIdCode(),
                DepositoryChannel.PING_AN, form.getLicense(),
                depositoryId, AccountStatus.CARD_NOT_BIND);
        return depositoryAccountRepository.save(depositoryAccount);
    }


    @Transactional(rollbackFor = Exception.class)
    public AuthInitResult applyDepositoryBindCard(DepositoryBindCardForm form, UserIdCode idCode) {

        DepositoryAccount depositoryAccount = form.getDepositoryAccount();
        Long remainSecond = 0L;

        List<DepositoryBankCard> bankCards = depositoryBankCardRepository
                .getByDepositoryAccountIdStatus(idCode, depositoryAccount.getDepositoryAccountId(),
                        List.of(BindStatus.SUCCESS, BindStatus.AUTHENTICATING));
        if (bankCards.size() > 1) {
            throw ApplicationException.error(ApplicationExceptionCode.DEP_BANK_CARD_BIND_MORE_ONE, idCode.getValue());
        } else if (bankCards.size() == 1) {
            DepositoryBankCard bankCard = bankCards.get(0);
            //已绑定
            if (bankCard.equalsCardNo(form.getCardNo())) {
                return new AuthInitResult(bankCards.get(0).getStatus(), "", remainSecond);
            } else {
                //已绑定了其他卡  换卡 本地解绑老的卡
                bankCard.logicalUnbind();
                depositoryBankCardRepository.updateBindStatus(bankCard);
            }
        }
        DepositoryBankCard depositoryBankCard =
                depositoryBankCardRepository.getByDepositoryAccountIdCardNo(idCode,
                        depositoryAccount.getDepositoryAccountId(), form.getCardNo());

        if (depositoryBankCard != null) {
            //本地为逻辑解绑状态 直接变更绑定成功
            if (BindStatus.LOGICAL_UNBIND == depositoryBankCard.getStatus()) {
                depositoryBankCard.bindSuccess();
                depositoryBankCardRepository.updateBindStatus(depositoryBankCard);
                depositoryAccount.changeStatus(AccountStatus.NORMAL);
                depositoryAccountRepository.updateStatus(depositoryAccount);
                return new AuthInitResult(BindStatus.SUCCESS, "", remainSecond);
                //本地为绑定成功 鉴权中状态 直接返回
            } else if (BindStatus.SUCCESS == depositoryBankCard.getStatus() ||
                    BindStatus.AUTHENTICATING == depositoryBankCard.getStatus()) {
                return new AuthInitResult(depositoryBankCard.getStatus(), "", remainSecond);
                //本地为初始化状态 在120s内重新提交 直接返回剩余时间
            } else if (BindStatus.INIT == depositoryBankCard.getStatus() &&
                    depositoryBankCard.remainSecond() > 0) {

                return new AuthInitResult(BindStatus.AUTHENTICATING,
                        "", depositoryBankCard.remainSecond());
            }

        }

        //查询平安绑卡状态 平安已绑卡 同步绑卡信息
        DepositoryBankCard syncBankCard = bankCardSyncCheck(form.getDepositoryAccount().getDepositoryId(), form.getCardNo());
        if (syncBankCard != null) {
            syncBankCard.sync(idCode, depositoryAccount.getDepositoryAccountId());
            depositoryBankCardRepository.save(syncBankCard);
            depositoryAccount.changeStatus(AccountStatus.NORMAL);
            depositoryAccountRepository.updateStatus(depositoryAccount);
            return new AuthInitResult(BindStatus.SUCCESS, "", remainSecond);
        }

        //请求平安 发起鉴权
        BindCardResult bindCardResult = remotePaymentService.applyBindCard(form);
        if (bindCardResult != null && bindCardResult.getResult()) {
            remainSecond = 120L;
            //本地有失败记录
            if (depositoryBankCard != null) {
                depositoryBankCard.retryBind(form.getBankName(),
                        form.getSuperBankCode(), form.getMobile());
                depositoryBankCardRepository.updateByBankCardId(depositoryBankCard);
                if (form.getCardType() == BankCardType.PUBLIC) {
                    depositoryAccount.changeStatus(AccountStatus.CARD_BINDING);
                    depositoryAccountRepository.updateStatus(depositoryAccount);
                }
            } else {
                //本地无记录
                if (form.getCardType() == BankCardType.PUBLIC) {
                    //对公账户 存入中间态
                    DepositoryBankCard bankCard = DepositoryBankCardFactory.createCompanyCard(form,
                            depositoryAccount.getDepositoryAccountId(), idCode,
                            BindStatus.AUTHENTICATING, LocalDateTime.now().plusDays(2));
                    depositoryBankCardRepository.save(bankCard);
                    depositoryAccount.changeStatus(AccountStatus.CARD_BINDING);
                    depositoryAccountRepository.updateStatus(depositoryAccount);
                } else {
                    //个人账户 存入初始化状态
                    DepositoryBankCard bankCard = DepositoryBankCardFactory.createCompanyCard(form,
                            depositoryAccount.getDepositoryAccountId(), idCode, BindStatus.INIT, LocalDateTime.now().plusMinutes(2));
                    depositoryBankCardRepository.save(bankCard);

                }
            }

            return new AuthInitResult(BindStatus.AUTHENTICATING, "", remainSecond);
        }


        return new AuthInitResult(BindStatus.FAIL,
                Optional.ofNullable(bindCardResult).map(BindCardResult::getMsg).orElse("绑卡失败"), remainSecond);


    }


    public DepositoryAccount accountSync(License license, UserIdCode idCode) {
        DepositoryAccount depositoryAccount = remotePaymentService.getOpenAccountSuccessInfo(license);
        if (depositoryAccount != null) {
            depositoryAccount.putIdCode(idCode);
            return depositoryAccountRepository.save(depositoryAccount);
        }
        return null;
    }

    public DepositoryBankCard bankCardSyncCheck(String depositoryId, String cardNo) {
        List<DepositoryBankCard> boundCardList = remotePaymentService.getBoundCardList(depositoryId);
        Map<String, DepositoryBankCard> boundMap = boundCardList.stream()
                .collect(Collectors.toMap(DepositoryBankCard::getCardNo, Function.identity()));
        return boundMap.get(cardNo);
    }


}
